package com.xinz.serialization;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;

import com.xinz.protocal.Log;

public class BeanInputStream extends DataInputStream{

	StreamContext context;
	
	/**
	 * 缓存区的对象
	 */
	ArrayList<Object> buffList = new ArrayList<Object>();
	
	public BeanInputStream(InputStream in, StreamContext context) {
		super(in);
		this.context = context;
	}
	
	public BeanInputStream(InputStream in) {
		this(in, new StreamContext());
	}
	
	/**
	 * 读取一个对象
	 * @return
	 * @throws Exception
	 */
	public Object readObject() throws Exception{
		Accessor accessor = new ObjectAccessor();
		try {
			readAccessor(accessor);
			return accessor.get();
		}
		catch(Exception e) {
			throw e;
		}
		finally {
			clearBuff();
		}
	}
	
	private void clearBuff() {
		buffList.clear();
	}
	
	/**
	 * 读取一个序列化实现对象
	 * @return
	 * @throws IOException
	 * @throws IllegalAccessException
	 * @throws ClassNotFoundException
	 */
	private Serialer readSerialer() throws IOException, ClassNotFoundException {
		int id = readShort();
		Serialer serialer;
		if(id < 0) {
			Class<?> clazz = readClass();
			int fieldSize = readShort();
			String[] fields = new String[fieldSize];
			for(int i = 0; i < fields.length; ++i) {
				fields[i] = readUTF();
			}
			serialer = new ObjectSerialer(clazz, fields);
			
			context.addSerialer(serialer);
		}
		else {
			serialer = context.getDynamic(id);
		}
		return serialer;
	}

	Class<?> readClass() throws IOException, ClassNotFoundException {
		int index = readShort();
		Class<?> result;
		if(index < 0) {
			result = Class.forName(readUTF());
			context.addClass(result);
		}
		else {
			result = context.getClass(index);
		}
		return result;
	}
	
	/**
	 * 读取一个对象或者字段，并根据读取类型填充到Accessor里
	 * @param accessor
	 * @throws Exception
	 */
	public void readAccessor(Accessor accessor) throws Exception {
		int flag = read();
		Serialer serialer;
		int index;
		switch(flag) {
		case StreamContext.HEAD_EMPTY:
			break;
		case StreamContext.HEAD_NULL:
			accessor.set(null);
			break;
		case StreamContext.HEAD_BASE:
			index = readShort();
			serialer = context.getBase(index);
			serialer.read(accessor, this);
			break;
		case StreamContext.HEAD_REF:
			index = readShort();
			accessor.set(buffList.get(index));
			break;
		case StreamContext.HEAD_NEW:
			accessor.set(null);
			while(true) {
				serialer = readSerialer();
				try {
					serialer.read(accessor, this);
					Class superClazz = serialer.getType().getSuperclass();
					if(superClazz == null || superClazz == Object.class || superClazz == Exception.class) {
						break;
					}
				}
				catch(Exception e) {
					Log.info("读取对象失败，Type：" + serialer.getType());
					e.printStackTrace();
				}
			}
			break;
		}
	}
	
	void addBuff(Object obj) {
		buffList.add(obj);
	}
}
